package qf.common.security.configure;


import com.alibaba.fastjson2.JSONObject;
import io.jsonwebtoken.Claims;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import qf.common.redis.constant.RedisConstant;
import qf.common.redis.utils.RedisUtil;
import qf.common.security.entitiy.SecuriyUserDetailVO;
import qf.common.security.entitiy.SysUser;
import qf.common.security.utils.JwtUtil;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;
import java.util.Set;

@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private static final Logger LOG = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);

    @Resource
    private RedisUtil redisUtil;

    @Value("#{'${qf.security.antMatchers}'.split(',')}")
    private Set<String> antMatchers;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if (antMatchers.contains(request.getRequestURI())) {
            // 如果是公共资源不需要权限的直接放行
            filterChain.doFilter(request,response);
            return;
        }

        //我们先拿到请求头中的token
        String token = request.getHeader("Authorization");

        if("".equals(token) || token == null){
            //说明没有携带token 那么直接放行 之后的过滤器肯定会报错，那么就说明用户没有登录
            throw new RuntimeException("非法操作，请登录");
        }
        //解析token
        String userid;
        try {
            Claims claims = JwtUtil.parseJWT(token);
            userid  = claims.getSubject();
        } catch (Exception e) {
            e.printStackTrace();
            //就说明token失效了 或者是token无效
            throw new RuntimeException("token无效");
        }
        //从redis中拿到用户的信息，给SecurityContextHolder设置上下文
        String redisKey = RedisConstant.USER_LOGIN_KEY + userid;
        LOG.info("redisKey:{},过期时间:{}",redisKey,redisUtil.getTime(redisKey));
        SecuriyUserDetailVO securiyUserDetailVO = JSONObject.parseObject(String.valueOf(redisUtil.get(redisKey)), SecuriyUserDetailVO.class);
        if(Objects.isNull(securiyUserDetailVO)
                || Objects.isNull(securiyUserDetailVO.getUser())
                || SysUser.STAT_DELETE.equals(securiyUserDetailVO.getUser().getEnabled())){
            throw new RuntimeException("用户非法操作");
        }
        //存入SecurityContextHolder上下文当中  注意 这里必须得使用三个参数的authentication
        //第三个参数为授权 也就是用户是啥身份 先不管
        Authentication authentication = new UsernamePasswordAuthenticationToken(securiyUserDetailVO,null, securiyUserDetailVO.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);
        //放行
        filterChain.doFilter(request,response); //那么就正常的请求接口去啦！！！
    }
}

